package com.lanyou.esb.cook.proxy.auth.processor.impl;

import java.util.Date;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.lanyou.esb.cook.proxy.auth.processor.VerifyAuthProcessor;
import com.lanyou.esb.cook.proxy.common.Constants;
import com.lanyou.esb.cook.proxy.common.SystemResCode;
import com.lanyou.esb.cook.proxy.entity.FieldSystem;
import com.lanyou.esb.cook.proxy.entity.Http;
import com.lanyou.esb.cook.proxy.entity.Token;
import com.lanyou.esb.cook.proxy.exception.AuthException;
import com.lanyou.esb.cook.proxy.meta.AuthType;
import com.lanyou.esb.cook.proxy.meta.TokenStatus;
import com.lanyou.esb.cook.proxy.service.impl.TraceLogServiceImpl;

/**
 * 基础验证类型验证处理器
 * 
 * @author Davey.wu
 */
public class DefaultVerifyAuthProcessor implements VerifyAuthProcessor {

	@Override
	public AuthType getAuthType() {
		return AuthType.HTTP_BASIC_KEY;
	}

	/**
	 * 认证权限
	 *
	 * @return
	 * @throws Exception
	 */
	@Override
	public boolean verify(FieldSystem system, Http interfaces,
			Map<String, Object> map, Token token) throws Exception {
		if (TraceLogServiceImpl.isTrace()) {
			// 记录跟踪日志
			TraceLogServiceImpl.addTraceLog(Constants.MSG_BEGIN_AUTH);
		}
		String applyKey = (String) map.get(Constants.APPLY_KEY);
		// 校验信息为空
		if (StringUtils.isBlank(applyKey)) {
			return false;
		}
		// 获取调用方系统编码
		String callSystemCode = (String) map.get(Constants.CALL_SYSTEM_CODE);
		if (StringUtils.isBlank(callSystemCode)) {
			return false;
		}
		// 对密钥进行解码
		applyKey = decodeApplyKey(applyKey);
		return validate(system, interfaces, applyKey, token);
	}

	private String decodeApplyKey(String applyKey) {
		// TODO 加密方式？
		// applyKey = getFromBASE64(applyKey);
		// TODO auth information format?
		return applyKey;
	}

	/**
	 * 校验
	 * 
	 * @param fieldSystem
	 * @param interfaces
	 * @param applyKey
	 * @param callSystemCode
	 * @return
	 * @throws Exception
	 */
	private boolean validate(FieldSystem fieldSystem, Http interfaces,
			String applyKey, Token token) throws Exception {
		// 找不到 令牌
		if (token == null) {
			if (TraceLogServiceImpl.isTrace()) {
				// 记录跟踪日志
				TraceLogServiceImpl.addTraceLog(
						SystemResCode.MSG_TOKEN_NOT_FOUND,
						Constants.FLAG_LEFT_SQUARE_BRACKET,
						Constants.SYSTEM_CODE, Constants.FLAG_EQUAL,
						fieldSystem.getCode(), Constants.FLAG_COMMA_SYMBOL,
						Constants.CALL_SYSTEM_CODE, Constants.FLAG_EQUAL,
						Constants.FLAG_COMMA_SYMBOL, Constants.INTERFACE_CODE,
						Constants.FLAG_EQUAL, interfaces == null ? ""
								: interfaces.getCode(),
						Constants.FLAG_COMMA_SYMBOL,
						Constants.INTERFACE_VERSION, Constants.FLAG_EQUAL,
						interfaces == null ? "" : interfaces.getVersion(),
						Constants.FLAG_RIGHT_SQUARE_BRACKET);
			}
			throw new AuthException(SystemResCode.MSG_TOKEN_NOT_FOUND,
					SystemResCode.CODE_TOKEN_NOT_FOUND);
		}
		// 令牌状态为不可用
		if (TokenStatus.DISABLE.ValueCode.equals(token.getStatus())) {
			if (TraceLogServiceImpl.isTrace()) {
				// 记录跟踪日志
				TraceLogServiceImpl.addTraceLog(
						SystemResCode.MSG_APPLYKEY_DISABLE,
						Constants.FLAG_LEFT_SQUARE_BRACKET, Constants.STATUS,
						token.getStatus(), Constants.FLAG_RIGHT_SQUARE_BRACKET);
			}
			throw new AuthException(SystemResCode.MSG_APPLYKEY_DISABLE,
					SystemResCode.CODE_APPLYKEY_DISABLE);
		}
		// 密钥过期时间为空
		if (token.getKeyInvalidDate() == null) {
			if (TraceLogServiceImpl.isTrace()) {
				// 记录跟踪日志
				TraceLogServiceImpl.addTraceLog(
						SystemResCode.MSG_APPLYKEY_EXPIRESIN_EMPTY,
						Constants.FLAG_LEFT_SQUARE_BRACKET,
						Constants.MSG_APPLY_KEY_INVALID_DATE,
						Constants.NULL_VALUE,
						Constants.FLAG_RIGHT_SQUARE_BRACKET);
			}
			throw new AuthException(SystemResCode.MSG_APPLYKEY_EXPIRESIN_EMPTY,
					SystemResCode.CODE_APPLYKEY_EXPIRESIN_EMPTY);
		}
		Date now = new Date();
		// 密钥已过期
		if (now.after(token.getKeyInvalidDate())) {
			if (TraceLogServiceImpl.isTrace()) {
				// 记录跟踪日志
				TraceLogServiceImpl.addTraceLog(
						SystemResCode.MSG_APPLYKEY_EXPIRED,
						Constants.FLAG_LEFT_SQUARE_BRACKET,
						Constants.MSG_APPLY_KEY_INVALID_DATE,
						Constants.FLAG_EQUAL, token.getKeyInvalidDate()
								.toLocaleString(), Constants.FLAG_COMMA_SYMBOL,
						Constants.MSG_CURRENT_TIME, Constants.FLAG_EQUAL, now
								.toLocaleString(),
						Constants.FLAG_RIGHT_SQUARE_BRACKET);
			}
			throw new AuthException(SystemResCode.MSG_APPLYKEY_EXPIRED,
					SystemResCode.CODE_APPLYKEY_EXPIRED);
		}

		// 密钥不正确
		if (StringUtils.isBlank(applyKey)
				|| applyKey.compareTo(token.getAppKey()) != 0) {
			if (TraceLogServiceImpl.isTrace()) {
				// 记录跟踪日志
				TraceLogServiceImpl.addTraceLog(
						SystemResCode.MSG_APPLYKEY_INVALID,
						Constants.FLAG_LEFT_SQUARE_BRACKET,
						Constants.APPLY_KEY, Constants.FLAG_EQUAL, applyKey,
						Constants.FLAG_RIGHT_SQUARE_BRACKET);
			}
			throw new AuthException(SystemResCode.MSG_APPLYKEY_INVALID,
					SystemResCode.CODE_APPLYKEY_INVALID);
		}
		return true;
	}

}
